#pragma once
#include "shader.h"
#include <stdio.h>
#include <iostream>
#include <sstream>
#include <vector>
#include <assert.h>
#include <gl/glew.h>
#include <gl/freeglut.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp> 

#include "ilcontainer.h"
#include "planar_mesh.h"

using namespace std;

struct WindowStruct
{
	glm::ivec2 grid_size;
	float (* function)(float);
	bool open;
};

class Window
{
public:

	GLsizei width;
	GLsizei height;
	GLuint window_handle;
	GLint period;
	GLsizei x;
	GLsizei y;
	ADSShader * shader;

	Window(GLsizei w, GLsizei h, ADSShader * shader);
	void DisplayMode(char * s, bool clear = false);
	void Display();

	
	//virtual void KeyboardFunc(unsigned char c, int x, int y) = 0;
	//virtual void TimerFunc(int value) = 0;
	bool PostGLInitialize(void * data);
	//virtual void TakeDown() = 0;

	void ApplyCustomization(float (* function)(float));

	void Axes()
	{
		GLboolean lighting_is_enabled = glIsEnabled(GL_LIGHTING);
		glDisable(GL_LIGHTING);
		glBegin(GL_LINES);
		glColor3f(1.0f, 0.0f, 0.0f);
		glVertex3f(0.0f, 0.0f, 0.0f);
		glVertex3f(1.0f, 0.0f, 0.0f);
		glColor3f(0.0f, 1.0f, 0.0f);
		glVertex3f(0.0f, 0.0f, 0.0f);
		glVertex3f(0.0f, 1.0f, 0.0f);
		glColor3f(0.0f, 0.0f, 1.0f);
		glVertex3f(0.0f, 0.0f, 0.0f);
		glVertex3f(0.0f, 0.0f, 1.0f);
		glEnd();
		if (lighting_is_enabled)
			glEnable(GL_LIGHTING);
	}

	PlanarMesh * planar_mesh;
	ADSShader fragment_shader;
	ADSShader vertex_shader;
	//ADSShader * shader;

	GLuint vertex_coordinate_handle;
	GLuint normal_value_handle;
	GLuint texture_coordinate_handle;
	GLuint vertex_array_handle;

	GLuint endcap_coordinate_handle;
	GLuint endcap_normal_handle;
	GLuint endcap_vertex_array_handle;

	ILContainer skybox_container;
	ILContainer normal_map_container;
	ILContainer second_normal_map_container;

	std::vector<glm::vec3> endcap_coordinates;
	std::vector<glm::vec3> endcap_normals;
	std::vector<glm::uint> endcap_triangle_indices;

	bool wireframe;
	bool draw_normals;
	bool do_flat_shading;
	bool force_open;
	bool do_normal_mapping;

	//Did not add destructor

	private:

	float (*function)(float);

	void InitializeGLHandles()
	{
		this->vertex_array_handle = BAD_GL_VALUE;
		this->vertex_coordinate_handle = BAD_GL_VALUE;
		this->texture_coordinate_handle = BAD_GL_VALUE;
		this->normal_value_handle = BAD_GL_VALUE;
		this->endcap_coordinate_handle = BAD_GL_VALUE;
		this->endcap_normal_handle = BAD_GL_VALUE;
		this->endcap_vertex_array_handle = BAD_GL_VALUE;
	}

	void MakeEndCap();
};
